iT邦幫忙

2024 iThome 鐵人賽

DAY 10
0

“React stands at the intersection of design and computer science, so both of these ideas are sources of inspiration.”

很喜歡這段話,前端有趣的點對我正是如此:在設計和技術間取得平衡。可以讓你寫的東西和使用者互動,串各種即時資料或功能,還美美的。

Takeaway

  • 原生DOM是命令式UI,React是聲明式UI
  • React將組件視為狀態機
  • 官方推薦在React重現UI的五步驟:列出視圖→觸發原因→寫好State→刪掉多餘→事件處理
  • Living Style Guide:列出各種可能視圖,就像設計系統。例如按鈕可能就有normal, hover, active, focus, disabled等狀態
  • Reducer可以合併多個State變數,減少多餘的。後續會學到
  • 切換布林時不是用setState(true),不然就會一直固定在true;而是要用setState(!state)才對

又是一次自己寫得開心,結果發現把img當成按鈕的挑戰一,限定不能再按一次圖片切回去,也就是說不能用三元運算,還要阻止跨父子影響的事件冒泡。

// 我原本寫的
import {useState} from 'react';

export default function Picture() {
  const [state, setState] = useState(false)

  function click() {
    setState(!state)
  }
  
  return (
    <div onClick={click} className={state ? "background background--active" : "background picture--active"}>
      <img
        className="picture"
        alt="Rainbow houses in Kampung Pelangi, Indonesia"
        src="https://i.imgur.com/5qwVYb1.jpeg"
      />
    </div>
  );
}
// 正解
import { useState } from 'react';

export default function Picture() {
  const [isActive, setIsActive] = useState(false);

  let backgroundClassName = 'background';
  let pictureClassName = 'picture';
  if (isActive) {
    pictureClassName += ' picture--active';
  } else {
    backgroundClassName += ' background--active';
  }

  return (
    <div
      className={backgroundClassName}
      onClick={() => setIsActive(false)}
    >
      <img
        onClick={e => {
          e.stopPropagation();
          setIsActive(true);
        }}
        className={pictureClassName}
        alt="Rainbow houses in Kampung Pelangi, Indonesia"
        src="https://i.imgur.com/5qwVYb1.jpeg"
      />
    </div>
  );
}

難度再升級的則是Edit mode和Save mode的轉換。列出視圖(兩種)和觸發原因(點擊)都不難,寫好State的部分則有「姓氏」、「名字」和「編輯中?」這三種會變化的部分。

這裡要特別小心,Form標籤也會因提不提交而改變!如果沒有透過onSubmit附加State的話,即使視圖成功切換了,畫面依然會自動重渲染。而Input自帶一個名為onChange的DOM事件,可以設定輸入的值正在改變時要做什麼。

再多筆記一點新手寫code可能會踩的小陷阱:像Takeaway裡也有寫到,但還是要不厭其煩提醒自己的,記得setter裡是寫「!state」。好容易因為前面設定false,直覺就在要切換時填上true。另外還有雖然無傷大雅,但符合coding style還是比較好的,事件處理函數通常以handle開頭的命名慣例。


上一篇
【Day9】State3
下一篇
【Day11】State managing 2
系列文
【現在學React還來得及嗎?】30天Takeaway分享30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
yc1996
iT邦新手 4 級 ‧ 2024-08-14 11:38:54

想請教大大,之前參考過一些開發者會這樣撰寫,這樣寫可以呢?

import React, { useCallback, useState } from "react";

/** - 測試頁面 */
export default function Page() {
  const [pageViewIndex, setPageViewIndex] = useState(false);
  const handleClickChangeEvt = useCallback(() => {
    setPageViewIndex((e) => !e);
  }, []);
  return <div></div>;
}

haruowang iT邦新手 5 級 ‧ 2024-08-14 14:27:15 檢舉

感謝你的回覆。
我本身還沒有在業界開發的經驗,所以如果要問我「什麼使用時機用什麼寫法比較好」,目前只能參考各路解釋回應。若有紕漏,請多包涵~

依據我目前的理解,useCallback可以拿來記憶函式,避免那個函式因為「跟它無關的變化」而重渲染。如果你的handleClickChangeEvt不希望被別的狀態改變所影響,或者你的頁面邏輯複雜到「有必要」做效能優化,再使用useCallback。不過如果只是想針對後者,有些狀況下雖然useCallback包起來的東西不會重渲染,但組件還是會,而造成多此一舉的浪費。

目前看到不少文章有再列出更細節,可以再研究看看~

(原來原PO回覆留言也要解新手任務哈哈哈)

我要留言

立即登入留言